﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SharpSoft.Lexing
{
    /// <summary>
    /// 字符扩展
    /// </summary>
    public static partial class Extensions
    {
        public static CharCategory GetCharCategory(this char c)
        {
            CharCategory cate = CharCategory.Unknow;
            if (c.IsDigit())
            {
                cate |= CharCategory.Digit;
            }
            else if (c.IsLower())
            {
                cate |= CharCategory.Lower;
            }
            else if (c.IsUpper())
            {
                cate |= CharCategory.Upper;
            }
            else if (c.IsEos())
            {
                cate |= CharCategory.EOS;
            }
            else if (c.IsWhiteSpace() || c == '\0')
            {
                cate |= CharCategory.WhiteSpace;
            }
            return cate;
        }

        public static bool MatchCategory(this char c, CharCategory cate1)
        {
            var cate = c.GetCharCategory();
            if (cate == cate1)
            {
                return true;
            }
            return cate != CharCategory.Unknow && (cate & cate1) == cate;
        }

        /// <summary>
        /// 判断字符是否为流结束标识
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsEos(this char c)
        {
            return c == '\0';
        }
        /// <summary>
        /// 判断字符是否为十进制数字
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsDigit(this char c)
        {
            return char.IsDigit(c);
        }
        /// <summary>
        /// 判断字符是否为16进制数字
        /// </summary>
        /// <returns></returns>
        public static bool IsHex(this char c)
        {
            if (c.IsDigit())
                return true;
            if (c == 'A' || c == 'a')
                return true;
            if (c == 'B' || c == 'b')
                return true;
            if (c == 'C' || c == 'c')
                return true;
            if (c == 'D' || c == 'd')
                return true;
            if (c == 'E' || c == 'e')
                return true;
            if (c == 'F' || c == 'f')
                return true;
            return false;
        }
        /// <summary>
        /// 判断字符是否为字母
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsLetter(this char c)
        {
            return char.IsLetter(c);
        }
        /// <summary>
        /// 判断字符是否为小写字母
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsLower(this char c)
        {
            return char.IsLower(c);
        }
        /// <summary>
        /// 判断字符是否为大写字母
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsUpper(this char c)
        {
            return char.IsUpper(c);
        }
        /// <summary>
        /// 判断字符是否为字母或数字
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsLetterOrDigit(this char c)
        {
            return char.IsLetterOrDigit(c);
        }
        /// <summary>
        /// 判断字符是否是控制字符
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsControl(this char c)
        {
            return char.IsControl(c);
        }
        /// <summary>
        /// 判断字符是否是符号
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsSymbol(this char c)
        {
            return char.IsSymbol(c);
        }
        /// <summary>
        /// 判断字符是否为空白，不仅限于空格
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsWhiteSpace(this char c)
        {
            switch (c)
            {
                //case '\xD':
                //case '\xA':
                //case '\x2028':
                //case '\x2029':

                case ' ':
                case '\n':
                case '\r':
                case '\f':
                case '\v':
                case '\t':
                case '\0':
                    return true;
                // Unicode
                default:
                    return (c > 127 && char.IsWhiteSpace(c));
            }
        }
        /// <summary>
        /// 判断字符是否属于分隔符
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsSeparator(this char c)
        {
            return char.IsSeparator(c);
        }
        /// <summary>
        /// 判断字符是否可以作为身份标识符，一般为字母、数字和下划线
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsIdentifier(this char c)
        {
            return c.IsLetterOrDigit() || c == '_';
        }

        /// <summary>
        /// 判断字符是否属于数字类别
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsNumber(this char c)
        {
            return char.IsNumber(c);
        }
        /// <summary>
        /// 判断字符是否具有代理项码位
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsSurrogate(this char c)
        {
            return char.IsSurrogate(c);
        }
        /// <summary>
        /// 判断字符与另一个字符是否形成代理项对
        /// </summary>
        /// <param name="c1"></param>
        /// <param name="c2"></param>
        /// <returns></returns>
        public static bool IsSurrogatePair(this char c1, char c2)
        {
            return char.IsSurrogatePair(c1, c2);
        }
        /// <summary>
        /// 判断字符是否是高代理项
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsHighSurrogate(this char c)
        {
            return char.IsHighSurrogate(c);
        }
        /// <summary>
        /// 判断字符是否是低代理项
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsLowSurrogate(this char c)
        {
            return char.IsLowSurrogate(c);
        }

        /// <summary>
        /// 判断字符是否属于标点符号
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsPunctuation(this char c)
        {
            return char.IsPunctuation(c);
        }
    }

    /// <summary>
    /// 字符分类
    /// </summary>
    [Flags]
    public enum CharCategory
    {
        Unknow = 0,
        /// <summary>
        /// 小写字母
        /// </summary>
        Lower,
        /// <summary>
        /// 大写字母
        /// </summary>
        Upper,
        /// <summary>
        /// 字母
        /// </summary>
        Letter = Lower | Upper,
        /// <summary>
        /// 数字
        /// </summary>
        Digit,
        /// <summary>
        /// 控制字符
        /// </summary>
        Control,
        /// <summary>
        /// 图形字符
        /// </summary>
        Graph,
        /// <summary>
        /// 标记字符
        /// </summary>
        Mark,
        /// <summary>
        /// 数据流结束标记。（该标记只限于对解码后的文本流有效，对于二进制数据无效）
        /// </summary>
        EOS,
        /// <summary>
        /// 在文档中不显示的空白字符，包括空格、Tab等等，空字符'\0'也属于其列。
        /// </summary>
        WhiteSpace,


        //TODO:收集其他的字符类型
    }
}
